package com.googlecode.animator.view.properties
{
	import com.googlecode.animator.data.Notifications;
	import com.googlecode.data.materials.BitmapFileMaterialVO;
	import com.googlecode.data.materials.ColorMaterialVO;
	import com.googlecode.data.materials.FileAssetMaterialVO;
	import com.googlecode.data.materials.MaterialVO;
	import com.googlecode.data.materials.MovieMaterialVO;
	import com.googlecode.data.materials.TextMaterialVO;
	import com.googlecode.data.materials.VideoStreamMaterialVO;
	import com.googlecode.data.objects3d.CameraProxyVO;
	import com.googlecode.data.objects3d.CubeVO;
	import com.googlecode.data.objects3d.MaterialsListObject3DVO;
	import com.googlecode.data.objects3d.Object3DVO;
	import com.googlecode.data.objects3d.PlaneVO;
	import com.googlecode.data.objects3d.SingleMaterialObject3DVO;
	import com.googlecode.data.objects3d.SphereVO;
	import com.googlecode.data.objects3d.TargetProxyVO;
	import com.googlecode.data.stage.StagePropertiesVO;
	import com.googlecode.animator.events.ColorChangeEvent;
	import com.googlecode.animator.events.PropertiesPanelEvent;
	import com.googlecode.animator.events.TextChangeEvent;
	import com.googlecode.animator.events.TransportControlslEvent;
	import com.googlecode.animator.model.ProjectSettingsProxy;
	import com.googlecode.animator.view.properties.types.Depth;
	import com.googlecode.animator.view.properties.types.DisplayFlatOnScreen;
	import com.googlecode.animator.view.properties.types.Divider;
	import com.googlecode.animator.view.properties.types.Height;
	import com.googlecode.animator.view.properties.types.Object3DName;
	import com.googlecode.animator.view.properties.types.RotationX;
	import com.googlecode.animator.view.properties.types.RotationY;
	import com.googlecode.animator.view.properties.types.RotationZ;
	import com.googlecode.animator.view.properties.types.StageHeight;
	import com.googlecode.animator.view.properties.types.StageWidth;
	import com.googlecode.animator.view.properties.types.Width;
	import com.googlecode.animator.view.properties.types.WorkAreaVisible;
	import com.googlecode.animator.view.properties.types.Xpos;
	import com.googlecode.animator.view.properties.types.Ypos;
	import com.googlecode.animator.view.properties.types.Zpos;
	
	import flash.events.Event;
	import flash.filesystem.File;
	import flash.net.FileFilter;
	import flash.utils.Dictionary;
	
	import mx.collections.ArrayCollection;
	import mx.controls.ComboBox;
	
	import org.puremvc.as3.multicore.interfaces.INotification;
	import org.puremvc.as3.multicore.patterns.mediator.Mediator;
	
	public class PropertiesPanelMediator extends Mediator
	{
		/**
		 * Identifier. 
		 */
		public static const NAME:String = "PropertiesPanelMediator";
		
		/**
		 * Reference to the object3D to which the properties relate. 
		 */
		private var _object3D:Object3DVO;
		
		/**
		 * Reference to the part of the properties panel dedicated to materials. 
		 */
		private var _ms:MaterialsEditor;
		
		/**
		 * Reference to the color material control. 
		 */
		private var _colorMaterialControl:ColorMaterialControl;
		
		/**
		 * Reference to the file material control 
		 */
		private var _fileMaterialControl:FileMaterialControl;
		
		/**
		 * Reference to the text material control 
		 */
		private var _textMaterialControl:TextMaterialControl;
		
		/**
		 * File object used to provide user with access to local file system. 
		 */
		private var _file:File;
		
		/**
		 * Constructor. 
		 * @param viewComponent
		 * 
		 */
		public function PropertiesPanelMediator(viewComponent:PropertiesPanel)
		{
			super(NAME, viewComponent);

		}
		
		/**
		 * Links in with the PureMVC framework. 
		 * 
		 */
		override public function onRegister():void
		{
			super.onRegister();
			
			viewRef.addEventListener(PropertiesPanelEvent.NAME, onPropertyChange);
			//viewRef.addEventListener(IndexChangedEvent.CHANGE, handleAccordianIndexChanged);
		}
		
		/**
		 * Clean up. 
		 * 
		 */
		override public function onRemove():void
		{
			super.onRemove();
			
			viewRef.propertiesPanel.removeEventListener(PropertiesPanelEvent.NAME, onPropertyChange);
		}
		
		/**
		 * List notification of interests. 
		 * @return 
		 * 
		 */
		override public function listNotificationInterests():Array
		{
			var list:Array = super.listNotificationInterests();
			
			list.push(Notifications.STAGE_WIDTH_UPDATED_MODEL);
			list.push(Notifications.STAGE_HEIGHT_UPDATED_MODEL);
			list.push(Notifications.DEFAULT_CAMERAS_ADDED_MODEL);
			list.push(Notifications.OBJECT3D_SELECTED_MODEL);
			list.push(Notifications.OBJECT3D_POSITION_CHANGED_MODEL);
			list.push(Notifications.OBJECT3D_DELETED_MODEL);
			list.push(Notifications.OBJECT3D_MATERIAL_UPDATED_MODEL);
			list.push(Notifications.OBJECT3D_DIMENSION_CHANGED_MODEL);
			
			return list;
		}
		
		/**
		 * Handle notification of interests. An object3D's will need to be updated
		 * 1. when it is selected
		 * 2. when its position changes
		 * 3. when it is deleted
		 * 4. when its material is changed
		 * 
		 * All of these events are EXTERNAL to the property controls themselves.
		 * @param notification
		 * 
		 */
		override public function handleNotification(notification:INotification):void
		{
			super.handleNotification(notification);
			
			switch(notification.getName())
			{
				case Notifications.STAGE_WIDTH_UPDATED_MODEL:
					
					handleStageWidthUpdated(notification.getBody() as StagePropertiesVO);
					
					break;
				
				case Notifications.STAGE_HEIGHT_UPDATED_MODEL:
					
					handleStageHeightUpdated(notification.getBody() as StagePropertiesVO);
					
					break;
					
				/* case Notifications.DEFAULT_CAMERAS_ADDED_MODEL:
					
					handleDefaultViewportsAdded();
					
					break; */ 
					
				case Notifications.OBJECT3D_SELECTED_MODEL:
					
					handleObject3DSelected(notification);
					
					break;
				
				case Notifications.OBJECT3D_POSITION_CHANGED_MODEL:
					
					handleObject3DPositionChanged(notification);
					
					break;
					
				case Notifications.OBJECT3D_DELETED_MODEL:
					
					handleObject3DDeleted();
	
					break;
					
				case Notifications.OBJECT3D_MATERIAL_UPDATED_MODEL:

					handleMaterialChanged(notification);
					
					break;				
				
				case Notifications.OBJECT3D_DIMENSION_CHANGED_MODEL:
				
					handleObject3DDimensionChangedModel(notification);
					
					break;
			}
		}
		
		protected function handleStageWidthUpdated(VO:StagePropertiesVO):void
		{
			viewRef.stageWidth = VO.stageWidth;
		}
		
		protected function handleStageHeightUpdated(VO:StagePropertiesVO):void
		{
			viewRef.stageHeight= VO.stageHeight;
		}
		
		/**
		 * Handle the case of an object3D being selected by the user. 
		 * @param notification
		 * 
		 */
		protected function handleObject3DSelected(notification:INotification):void
		{	
			// remove all previous items. we need to start with a blank canvas
			viewRef.cleanup();
			trace("W"+notification.getBody() as String);
			// get a reference to the object3D
			var name:String = notification.getBody() as String;
			_object3D = settings.getObject3D(name);
			
			// do the core properties
			coreProperties(_object3D);
			
			// apportion tasks according to type of object3D
			if(_object3D is PlaneVO)
			{
				handlePlaneSelected(_object3D as PlaneVO);
			}
			
			if(_object3D is CubeVO)
			{
				handleCubeSelected(_object3D as CubeVO);
			}
			
			if(_object3D is SphereVO)
			{
				handleSphereSelected(_object3D as SphereVO);
			}
			
			// we also need to deal with the object3D's material(s)
			// 1. prepare
			// if the materials editor already exists, remove any event listeners
			if(_ms)
			{
				_ms.removeEventListener(Event.CHANGE, onFaceChange);
				_ms.materialControl.typeList.removeEventListener(Event.CHANGE, onTypeListChange);
			}
			
			// if either the camera proxy or the target proxy have been selected, go no further
			if(_object3D is CameraProxyVO || _object3D is TargetProxyVO)
			{
				viewRef.removeMaterialsSection();
				return;
			} 
			
			// 2. create new materials section
			_ms = new MaterialsEditor();
			
			// add materials editor
			viewRef.addMaterialsSection(_ms);
			
			// add event listeners
			_ms.faceList.addEventListener(Event.CHANGE, onFaceChange);
			_ms.materialControl.typeList.addEventListener(Event.CHANGE, onTypeListChange);
				
			if(_object3D is MaterialsListObject3DVO)
			{

				if((_object3D as MaterialsListObject3DVO).selectedFace == null)
				{
					(_object3D as MaterialsListObject3DVO).selectedFace = CubeVO.BACK_FACE;
				}
				handleMaterialsListObject3DSelected(_object3D as MaterialsListObject3DVO);
			}
			
			if(_object3D is SingleMaterialObject3DVO)
			{
				handleSingleMaterialObject3DSelected(_object3D as SingleMaterialObject3DVO);
			}
		}
		
		/**
		 * Handle the repositioning of an object3D. 
		 * @param notification
		 * 
		 */
		protected function handleObject3DPositionChanged(notification:INotification):void
		{
			var name:String = notification.getBody() as String;
			var VO:Object3DVO = settings.getObject3D(name);
			
			viewRef.update(Xpos.NAME, VO.x);
			viewRef.update(Ypos.NAME, VO.y);
			viewRef.update(Zpos.NAME, VO.z);
		}
		
		/**
		 * Handle the deletion of an object3D. 
		 * 
		 */
		protected function handleObject3DDeleted():void
		{
			viewRef.cleanup();
		}
		
		/**
		 * In this case the handler ensures all the information is updated if a material
		 * is changed. It assumes the object3D must still be selected. 
		 * @param notification
		 * 
		 */		 
		protected function handleMaterialChanged(notification:INotification):void
		{
			// set a permanent reference to the object3D
			if(notification.getBody() as Object3DVO != null)
			{
				_object3D = notification.getBody() as Object3DVO;
			}
			
			var mat:MaterialVO;
			var face:String
			
			// update the faceList combo box, then set its selectedItem, and finally set up the controls.
			if(_object3D is MaterialsListObject3DVO)
			{	
				var mList:Dictionary = (_object3D as MaterialsListObject3DVO).materialsList;
				_ms.loadMultiFaceToList(mList);

				face = (_object3D as MaterialsListObject3DVO).selectedFace;
				mat = mList[face];
				
				if(mat != null)
				{
					_ms.setFaceListSelectedItem(mat);
				}
				
			}
			
			// same thing for a single material object3D, with fewer steps
			if(_object3D is SingleMaterialObject3DVO)
			{	
				mat = (_object3D as SingleMaterialObject3DVO).material;
				
				var list:ArrayCollection = new ArrayCollection([{label:mat.face, data:mat}]);		
				
				_ms.loadSingleFaceToList(list);
			}
			
			// load the media square
			_ms.loadMediaSquare(mat);
			
			// set up the controls depending on what has been selected
			if(mat is FileAssetMaterialVO)
			{
				setFileMaterialControls(mat);
			}
			
			if(mat is ColorMaterialVO)
			{
				setColorMaterialControls();
			}
			
			if(mat is TextMaterialVO)
			{
				setTextMaterialControls();
			}
		}
		
		protected function handleObject3DDimensionChangedModel(notification:INotification):void
		{
			var name:String = notification.getBody() as String;
			
			_object3D = settings.getObject3D(name);
			
		}
		
		/**
		 * Some properties are common to all objects3D. These are dealt with separately, for convenience. 
		 * @param VO
		 * 
		 */
		protected function coreProperties(VO:Object3DVO):void
		{
			var name:Object3DName = new Object3DName();
			name.label = "Name:";
			name.propertyValue = VO.label;
			
			var xPos:Xpos = new Xpos();
			xPos.label = "X Position:";
			xPos.propertyValue = String(VO.x);
			
			var yPos:Ypos = new Ypos();
			yPos.label = "Y Position:";
			yPos.propertyValue = String(VO.y);
			
			var zPos:Zpos = new Zpos();
			zPos.label = "Z Position:";
			zPos.propertyValue = String(VO.z);
			
			viewRef.addProperty(new Divider());
			viewRef.addProperty(name);
			viewRef.addProperty(xPos);
			viewRef.addProperty(yPos);
			viewRef.addProperty(zPos);
			viewRef.addProperty(new Divider());
			
			if(_object3D is CameraProxyVO == false && _object3D is TargetProxyVO == false)
			{
				var rotationX:RotationX = new RotationX();
				rotationX.label = "Rotation X:";
				rotationX.propertyValue = String(VO.rotationX);
				
				var rotationY:RotationY = new RotationY();
				rotationY.label = "Rotation Y:";
				rotationY.propertyValue = String(VO.rotationY);
				
				var rotationZ:RotationZ = new RotationZ();
				rotationZ.label = "Rotation Z:";
				rotationZ.propertyValue = String(VO.rotationZ);
				
				viewRef.addProperty(rotationX);
				viewRef.addProperty(rotationY);
				viewRef.addProperty(rotationZ);
				viewRef.addProperty(new Divider());
			}
			
		}
		
		/**
		 * Some properties only relate to planes. Add them. 
		 * @param VO
		 * 
		 */
		protected function handlePlaneSelected(VO:PlaneVO):void
		{
			
			var w:Width = new Width();
			var h:Height = new Height();
			var billboard:DisplayFlatOnScreen = new DisplayFlatOnScreen();
			
			w.label = "Width:";
			w.propertyValue = String(int(VO.width * VO.scaleX));

			h.label = "Height:";
			h.propertyValue = String(int(VO.height * VO.scaleY));
			
			billboard.label = "Billboard?:";
			
			viewRef.addProperty(w);
			viewRef.addProperty(h);
			viewRef.addProperty(new Divider());
			viewRef.addProperty(billboard);

		}
		
		/**
		 * Some properties only relate to cubes. Add them. 
		 * @param VO
		 * 
		 */
		protected function handleCubeSelected(VO:CubeVO):void
		{
			var w:Width = new Width();
			var h:Height = new Height();
			var d:Depth = new Depth();
			
			w.label = "Width:";
			w.propertyValue = String(int(VO.width * VO.scaleX));
			
			h.label = "Height:";
			h.propertyValue = String(int(VO.height * VO.scaleY));
			
			d.label = "Depth:";
			d.propertyValue = String(int(VO.depth * VO.scaleZ));
			
			viewRef.addProperty(w);
			viewRef.addProperty(h);
			viewRef.addProperty(d);
			viewRef.addProperty(new Divider());
			
			
		}
		
		/**
		 * Some properties only relate to spheres. Add them. 
		 * @param VO
		 * 
		 */
		protected function handleSphereSelected(VO:SphereVO):void
		{
			
		}
		
		/**
		 * Whenever a multi-faced object3D is selected, the properties panel is populated with 
		 * a complete set of properties relating to that object3D.
		 *  
		 * @param VO
		 * 
		 */
		protected function handleMaterialsListObject3DSelected(VO:MaterialsListObject3DVO):void
		{
			
			
			// 1. set up faces combo box and edit controls

			var mList:Dictionary = VO.materialsList;
			_ms.loadMultiFaceToList(mList);
			
			// 1.a set the face list to the selected item
			_ms.setFaceListSelectedItem(mList[VO.selectedFace]);
			
			// 2. retrieve the selected material
			var defaultMat:MaterialVO = _ms.faceList.selectedItem.data;
			
			// 3. set up the media square
			_ms.loadMediaSquare(defaultMat);

			// 4. set the type list to the current material
			_ms.setTypeListSelectedItem(defaultMat);
			
			// 5. set the controls
			if(defaultMat is FileAssetMaterialVO)
			{
				setFileMaterialControls(defaultMat);
			}	
			
			if(defaultMat is ColorMaterialVO)
			{
				setColorMaterialControls();
			}	
			
			if(defaultMat is TextMaterialVO)
			{
				setTextMaterialControls();
			}
		}
		
		/**
		 * Whenever an single material object3D is selected, the properties panel 
		 * is populated with a complete set of properties relating to that object3D. 
		 * 
		 * @param VO
		 * 
		 */
		protected function handleSingleMaterialObject3DSelected(VO:SingleMaterialObject3DVO):void
		{
			var list:ArrayCollection = new ArrayCollection();
			var obj:Object = new Object();
			
			obj.label = VO.material.face;
			obj.data = VO.material;
			
			list.addItem(obj);
			
			_ms.loadSingleFaceToList(list);
			
			_ms.loadMediaSquare(VO.material);
			
			_ms.setTypeListSelectedItem(VO.material);
			
			if(VO.material is FileAssetMaterialVO)
			{
				setFileMaterialControls(VO.material);
			}
			
			if(VO.material is ColorMaterialVO)
			{
				setColorMaterialControls();
			}
			
			if(VO.material is TextMaterialVO)
			{
				setTextMaterialControls();
			}
	
		}
		
		/////////////////////////////////////////////////
		//
		// Changes from PropertiesPanel
		//
		/////////////////////////////////////////////////
		
		/**
		 * Responds to the user changing positional or rotational or any other properties. 
		 * @param evt
		 * 
		 */
		protected function onPropertyChange(evt:PropertiesPanelEvent):void
		{
			// handle stage width or height changes
			var stageObj:StagePropertiesVO;
			
			if(evt.target is StageWidth || evt.target is StageHeight)
			{
				stageObj = new StagePropertiesVO();
				
				stageObj.stageWidth = settings.stageWidth;
				stageObj.stageHeight = settings.stageHeight;
				
				if(evt.target is StageWidth)
				{
					stageObj.stageWidth = int((evt.target as StageWidth).propertyValue);
				}else
				{
					stageObj.stageHeight = int((evt.target as StageHeight).propertyValue);
				}
				
				sendNotification(Notifications.SET_STAGE_SIZE_MODEL, stageObj);
				
				return;
			}
			
			// handle the work area's visibility being set
			if(evt.target is WorkAreaVisible)
			{
				stageObj = new StagePropertiesVO();
				stageObj.workAreaVisible = (evt.target as WorkAreaVisible).propertyValue;

				sendNotification(Notifications.SET_WORK_AREA_VISIBLE, stageObj);
				
				return;
			}
			
			(evt as PropertiesPanelEvent).VO.name = _object3D.name;
			
			sendNotification(Notifications.UPDATE_PROPERTY_MODEL, evt);
		}
		
		/**
		 * Responds to the user selecting a new face. 
		 * @param evt
		 * 
		 */
		protected function onFaceChange(evt:Event):void
		{
			var mat:MaterialVO = (evt.target as ComboBox).selectedItem.data;
			
			// if the user changes the selected face, the permanent reference _object3D also has to be updated
			if(_object3D is MaterialsListObject3DVO)
			{
				(_object3D as MaterialsListObject3DVO).selectedFace = mat.face;
			}
					
			_ms.loadMediaSquare(mat);
			
			_ms.setTypeListSelectedItem(mat);
			
			if(mat is FileAssetMaterialVO)
			{
				setFileMaterialControls(mat);
			}
			
			if(mat is ColorMaterialVO)
			{
				setColorMaterialControls();
			}
			
			if(mat is TextMaterialVO)
			{
				setTextMaterialControls();
			}
			
		}
		
		/**
		 * If the user changes the type of material, the controls need to be updated. 
		 * @param evt
		 * 
		 */
		protected function onTypeListChange(evt:Event):void
		{
			var matClass:Class = (evt.target as ComboBox).selectedItem.data;
			var mat:MaterialVO = _ms.faceList.selectedItem.data;
			
			if(matClass == FileAssetMaterialVO)
			{
				setFileMaterialControls(mat);
			}

			if(matClass == ColorMaterialVO)
			{
				setColorMaterialControls();
			}
			
			if(matClass == TextMaterialVO)
			{
				setTextMaterialControls();
			}
			
		}
		
		/**
		 * Adds the controls needed to change a colour or alpha of the material. 
		 * 
		 */
		protected function setColorMaterialControls():void
		{
			var mat:MaterialVO = _ms.faceList.selectedItem.data;
			
			_colorMaterialControl = new ColorMaterialControl();
			
			_ms.addEditControls(_colorMaterialControl);
			
			if(mat is ColorMaterialVO)
			{
				_colorMaterialControl.fillAlpha.value = (mat as ColorMaterialVO).fillAlpha * 100;
				_colorMaterialControl.fillColor.selectedColor = (mat as ColorMaterialVO).fillColor;
			}
			
			_colorMaterialControl.addEventListener(ColorChangeEvent.NAME, onSubmitProperty);
		}
		
		/**
		 * Responds to the user submitting a new colour of alpha setting. 
		 * @param evt
		 * 
		 */
		protected function onSubmitProperty(evt:*):void
		{
			var mat:MaterialVO = evt.VO as MaterialVO;
			mat.face = (_ms.faceList.selectedItem.data as MaterialVO).face;
			
			var object3D:Object3DVO = addMaterialToObject3D(_object3D, mat);
 	
			if(object3D is MaterialsListObject3DVO)
			{
				(object3D as MaterialsListObject3DVO).selectedFace = (_ms.faceList.selectedItem.data as MaterialVO).face;
			}
			
			if(object3D is SingleMaterialObject3DVO)
			{
				(object3D as SingleMaterialObject3DVO).material = mat;
			}
			sendNotification(Notifications.UPDATE_OBJECT3D_MATERIAL_MODEL, object3D);
		}
		
		protected function setTextMaterialControls():void
		{
			var mat:MaterialVO = _ms.faceList.selectedItem.data;
			
			_textMaterialControl = new TextMaterialControl();
			
			_ms.addEditControls(_textMaterialControl);
			
			if(mat is TextMaterialVO)
			{
				_textMaterialControl.text.text = (mat as TextMaterialVO).text;
			}
			
			_textMaterialControl.addEventListener(TextChangeEvent.NAME, onSubmitProperty);
			
		}
		
		/* protected function onSubmitText(evt:TextChangeEvent):void
		{
			var mat:MaterialVO = evt.VO as MaterialVO;
			mat.face = (_ms.faceList.selectedItem.data as MaterialVO).face;
			
			var object3D:Object3DVO = addMaterialToObject3D(_object3D, mat);
 	
			if(object3D is MaterialsListObject3DVO)
			{
				(object3D as MaterialsListObject3DVO).selectedFace = (_ms.faceList.selectedItem.data as MaterialVO).face;
			}
			
			sendNotification(Notifications.UPDATE_OBJECT3D_MATERIAL_MODEL, object3D);
		} */
		
		/**
		 * Adds the controls needed to change a file material. 
		 * 
		 */
		protected function setFileMaterialControls(matVO:MaterialVO):void
		{
			if(_fileMaterialControl)
			{
				_fileMaterialControl.removeEventListener(FileMaterialControl.LOAD, onBrowse);
				_fileMaterialControl.removeEventListener(TransportControlslEvent.NAME, onTransportControls);
			}
			
			_fileMaterialControl = new FileMaterialControl();
			
			if(matVO is VideoStreamMaterialVO)
			{
				_fileMaterialControl.addTransportControlsTickbox((matVO as VideoStreamMaterialVO).showControls);
				_fileMaterialControl.addEventListener(TransportControlslEvent.NAME, onTransportControls);
			}
			
			if(matVO is MovieMaterialVO)
			{
				_fileMaterialControl.addTransportControlsTickbox((matVO as MovieMaterialVO).showControls);
				_fileMaterialControl.addEventListener(TransportControlslEvent.NAME, onTransportControls);
			}
			
			_fileMaterialControl.addEventListener(FileMaterialControl.LOAD, onBrowse);
			
			
			_ms.addEditControls(_fileMaterialControl);
		}
		
		/**
		 * The Browse button enables users to navigate to an appropriate file. 
		 * @param evt
		 * 
		 */
		protected function onBrowse(evt:Event):void
		{
			var ff:FileFilter = new FileFilter("SWF, FLV, Image", "*.swf; *.flv; *.gif; *.jpg; *.jpeg; *.png;");
			
			if(_file == null)
			{
				_file = File.documentsDirectory;
			}
				
			_file.addEventListener(Event.SELECT, onFileSelect);
			_file.browseForOpen("Open",[ff]);
		}
		
		/**
		 * Called when a user selects a file  for a material. 
		 * @param evt
		 * 
		 */
		protected function onFileSelect(evt:Event):void
		{	
			_file.removeEventListener(Event.SELECT, onFileSelect);
			
			var length:uint = ((evt.target as File).nativePath as String).length;
			var fp:String = (evt.target as File).url;
			
			var mat:MaterialVO;
		
			if(fp.search(".jpg") != -1 || fp.search(".jpeg") != -1 || fp.search(".gif") != -1 || fp.search(".png") != -1)
			{
				mat = new BitmapFileMaterialVO();
				(mat as BitmapFileMaterialVO).filePath = fp;
				
			}else if(fp.search(".swf") != -1)
			{
				mat = new MovieMaterialVO();
				(mat as MovieMaterialVO).filePath = fp;

			}else if(fp.search(".flv") != -1)
			{
				mat = new VideoStreamMaterialVO();
				(mat as VideoStreamMaterialVO).filePath = fp;
				
			}else
			{
				return;
			}
			
			mat.face = _ms.faceList.selectedItem.data.face;

			sendNotification(Notifications.UPDATE_OBJECT3D_MATERIAL_MODEL, addMaterialToObject3D(_object3D, mat));
		}
		
		protected function onTransportControls(evt:TransportControlslEvent):void
		{
			var mat:MaterialVO = _ms.faceList.selectedItem.data;
			
			if(mat is VideoStreamMaterialVO)
			{
				(mat as VideoStreamMaterialVO).showControls = evt.VO.visible;
			}
			
			if(mat is MovieMaterialVO)
			{
				(mat as MovieMaterialVO).showControls = evt.VO.visible;
			}
			
			
			sendNotification(Notifications.SET_MATERIAL_TRANSPORT_CONTROLS_MODEL, addMaterialToObject3D(_object3D, mat));
		}
		/**
		 * Adds a material to an object3D.
		 *  
		 * @param object3D
		 * @param mat
		 * @return 
		 * 
		 */
		protected function addMaterialToObject3D(object3D:Object3DVO, mat:MaterialVO):Object3DVO
		{
			if(object3D is SingleMaterialObject3DVO)
			{
				(object3D as SingleMaterialObject3DVO).material = mat;
			}
			
			if(object3D is MaterialsListObject3DVO)
			{
				(object3D as MaterialsListObject3DVO).materialsList[(object3D as MaterialsListObject3DVO).selectedFace] = mat;
			}
			
			return object3D;
		}
		
		/////////////////////////////////////////////////
		//
		// Utils
		//
		/////////////////////////////////////////////////
		
		/**
		 * Returns typed reference to the model. 
		 * @return 
		 * 
		 */
		protected function get settings():ProjectSettingsProxy
		{		
			return facade.retrieveProxy(ProjectSettingsProxy.NAME) as ProjectSettingsProxy;
		}
		
		/**
		 * Returns typed reference to component. 
		 * @return 
		 * 
		 */
		protected function get viewRef():PropertiesPanel
		{
			return viewComponent as PropertiesPanel
		}
	}
}